package com.personal.android.general;

import android.app.ActivityManager;
import android.content.Context;
import android.os.Build;
import android.os.Looper;
import android.text.TextUtils;
import com.personal.android.general.utils.AppInfoUtils;
import com.personal.android.general.utils.ConfigUtils;
import com.personal.android.general.utils.DisplayUtils;
import com.personal.android.general.utils.TelephoneInfoUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.List;

/**
 * Created by winter on 2015/9/22.
 *
 * @author winter
 */
public class GeneralUtils {
    public static boolean isUiThread() {
        return Looper.myLooper() ==Looper.getMainLooper();
    }

    public static boolean isForeground() {
        String packageName = BaseApplication.getBaseApplication().getPackageName();

        ActivityManager activityManager = (ActivityManager) BaseApplication.getBaseApplication().getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
        if (appProcesses == null) {
            return false;
        }

        for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
            if (packageName.equals(appProcess.processName)) {
                return appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
            }
        }
        return false;
    }

    public static boolean isAppOnForeground() {
        String packageName = BaseApplication.getBaseApplication().getPackageName();
        ActivityManager activityManager = (ActivityManager) BaseApplication.getBaseApplication().getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningTaskInfo> taskInfos = activityManager.getRunningTasks(1);

        return taskInfos.size() > 0 && TextUtils.equals(packageName, taskInfos.get(0).topActivity.getPackageName());
    }

    private static final int OBJECT_HEADER_SIZE = 8;
    private static final int OBJECT_ALIGNMENT = 8;
    private static final int ARRAY_HEADER_SIZE = 12;

    /**
     * 只会计算浅大小(boolean,byte,short,char,int,float,long,double,String,reference)
     * @param object object
     * @return 对象的浅大小
     */
    public static int sizeOf(Object object) {
        if (object == null) {
            return 0;
        }
        int total = 0;
        if (object.getClass().isArray()) {
            total += ARRAY_HEADER_SIZE;

            int stringSize = 0;
            if (object instanceof long[]) {
                total += ((long[])object).length * 8;
            } else if (object instanceof double[]) {
                total += ((double[])object).length * 8;
            } else if (object instanceof int[]) {
                total += ((int[])object).length * 4;
            } else if (object instanceof float[]) {
                total += ((float[])object).length * 4;
            } else if (object instanceof short[]) {
                total += ((short[])object).length * 2;
            } else if (object instanceof char[]) {
                total += ((char[])object).length * 2;
            } else if (object instanceof byte[]) {
                total += ((byte[])object).length;
            } else if (object instanceof boolean[]) {
                total += ((boolean[])object).length;
            } else if (object instanceof String[]) {
                stringSize = getStringArraySize((String[])object);
            } else {
                total += ((Object[])object).length * 4;
            }
            total = align(total);
            total += stringSize;
        } else {
            total += OBJECT_HEADER_SIZE;
            int stringSize = 0;
            for (Class<?> cls = object.getClass(); cls != null; cls = cls.getSuperclass()) {
                int eightByteCount = 0;
                int fourByteCount = 0;
                int twoByteCount = 0;
                int oneByteCount = 0;
                int referenceCount = 0;

                Field[] fields = cls.getDeclaredFields();
                for (Field field : fields) {
                    if (!Modifier.isStatic(field.getModifiers())) {
                        Class<?> fieldCls = field.getType();
                        if (fieldCls == long.class || fieldCls == double.class) {
                            eightByteCount++;
                        } else if (fieldCls == int.class || fieldCls == float.class) {
                            fourByteCount++;
                        } else if (fieldCls == short.class || fieldCls == char.class) {
                            twoByteCount++;
                        } else if (fieldCls == boolean.class || fieldCls == byte.class) {
                            oneByteCount++;
                        } else if (fieldCls == String.class) {
                            field.setAccessible(true);
                            try {
                                Object o = field.get(object);
                                if (o != null) {
                                    String str = o.toString();
                                    stringSize += getStringSize(str);
                                }
                            } catch (IllegalAccessException e) {
                                e.printStackTrace();
                            }
                        } else {
                            referenceCount++;
                        }
                    }
                }
                total += eightByteCount * 8 + fourByteCount * 4 + twoByteCount * 2 + oneByteCount;
                total = align(total);
                total += referenceCount * 4;
                total = align(total);
            }
            total += stringSize;
        }
        return total;
    }

    public static int getStringArraySize(String [] strings) {
        int total = 12 + strings.length * 4;
        total = align(total);
        for (String s : strings) {
            total += getStringSize(s);
        }
        return total;
    }

    public static int getStringSize(String str) {
        int contentSize = str.length() * 2 + 12;
        contentSize = align(contentSize);
        return 32 + contentSize;
    }

    private static int align(int size) {
        if ((size % OBJECT_ALIGNMENT) != 0) {
            size += OBJECT_ALIGNMENT - (size % OBJECT_ALIGNMENT);
        }
        return size;
    }

    public static String getDeviceInfo() {
        StringBuilder builder = new StringBuilder();
        builder.append("brand: ").append(Build.BRAND).append("\n")
                .append("manufacturer: ").append(Build.MANUFACTURER).append("\n")
                .append("DeviceName: ").append(TelephoneInfoUtils.getDeviceName()).append("\n")
                .append("DeviceVersion: ").append(TelephoneInfoUtils.getDeviceVersion()).append("\n")
                .append("sdk: ").append(Build.VERSION.SDK_INT).append("\n")
                .append("IMEI: ").append(TelephoneInfoUtils.getIMEI()).append("\n")
                .append("Display: ").append(DisplayUtils.getDisplayWidth()).append(" x ").append(DisplayUtils.getDisplayHeight()).append("\n")
                .append("SimState: ").append(TelephoneInfoUtils.getSimState()).append("\n")
                .append("PhoneNumber: ").append(TelephoneInfoUtils.getPhoneNumber()).append("\n")
                .append("ProvidersName: ").append(TelephoneInfoUtils.getProvidersName()).append("\n")
                .append("PhoneType: ").append(TelephoneInfoUtils.getPhoneType()).append("\n")
                .append("App VersionName: ").append(AppInfoUtils.getVersionName()).append("\n")
                .append("Build Time: ").append(ConfigUtils.getBuildTime()).append("\n");
        return builder.toString();
    }
}
